package com.hp.bon.sgw.util.dcc;

import java.util.Date;
import java.util.Iterator;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.hp.bon.sgw.Constants;
import com.hp.bon.sgw.Constants.NodeType;
import com.hp.bon.sgw.bean.CapabilityCtrlBean;
import com.hp.bon.sgw.domain.Node;
import com.hp.bon.sgw.service.ConfigService;
import com.hp.bon.sgw.start.SpringContext;
import com.hp.bon.sgw.util.Comutils;
import com.hp.ocs.diameter.message.AVP;
import com.hp.ocs.diameter.message.AVP_Grouped;
import com.hp.ocs.diameter.message.AVP_Time;
import com.hp.ocs.diameter.message.AVP_UTF8String;
import com.hp.ocs.diameter.message.AVP_Unsigned32;
import com.hp.ocs.diameter.message.DictionaryManager;
import com.hp.ocs.diameter.message.Message;

/**
 * 对DCC消息进行装饰，如加入某些AVP，删除某些AVP，用于BON网内网外DCC消息的AVP封装控制
 * 
 * @author wuzhih
 * 
 */

public class DCCMsgDecorator {

	private static DCCMsgDecorator instance;

	public static DCCMsgDecorator getInstance() {
		if (instance == null) {
			instance = new DCCMsgDecorator();
		}
		return instance;
	}

	public static DictionaryManager _dic = DictionaryManager.getInstance();
	/**
	 * Logger for this class
	 */
	private static final Logger logger = LoggerFactory.getLogger(DCCMsgDecorator.class);

	private ConfigService confSrv = SpringContext.getInstance().getConfigService();
	private long seq = 0;
	Set<Integer> removedAVPCodes;

	public void decorateMsg(Message msg, Node fromNode, Node toNode) {
		if (msg.find(Constants.DIAMETER_AVP_EVENT_TIMESTAMP) == null) {
			AVP eventTime = new AVP_Time(Constants.DIAMETER_AVP_EVENT_TIMESTAMP, new Date());
			eventTime.setMandatory(true);
			msg.add(eventTime);
		}
		if (msg.find(Constants.DIAMETER_AVP_CC_REQUEST_TYPE) == null) {
			AVP reqType = new AVP_Unsigned32(Constants.DIAMETER_AVP_CC_REQUEST_TYPE, 4);
			reqType.setMandatory(true);
			msg.add(reqType);
			AVP reqNum = new AVP_Unsigned32(Constants.DIAMETER_AVP_CC_REQUEST_NUMBER, 0);
			reqNum.setMandatory(true);
			msg.add(reqNum);
			AVP reqAct = new AVP_Unsigned32(Constants.DIAMETER_AVP_CC_REQUEST_ACTION, Constants.DIAMETER_AVP_CC_REQUEST_ACTION_TYPE__BS);
			reqAct.setMandatory(true);
			msg.add(reqAct);
		}

		if (toNode.getNodeType() == NodeType.NODE_SR|| toNode.getNodeType() == NodeType.NODE_DCC_BON) {// 发给BON网的CCR
			// 增加必须的控制字段
			//logger.debug("addBonControlAVPs");
			addBonControlAVPs(msg, fromNode);
		} else {// 转发给网元时，删除BON网定义的特定的AVP
			removeControlAVPs(msg);
		}
	}

	private void removeControlAVPs(Message msg) {
		if (removedAVPCodes == null || removedAVPCodes.isEmpty()) {
			return;
		}
		Iterator<AVP> msgAVPItors = msg.iterator();
		while (msgAVPItors.hasNext()) {
			AVP avp = msgAVPItors.next();
			if (avp.vendorID() == Constants.DIAMETER_VENDOR_CT && removedAVPCodes.contains(avp.code())) {
				msgAVPItors.remove();
			}
		}
	}

	private void addBonControlAVPs(Message msg, Node fromNode) {
		final String dateFmt = "yyyyMMddHHmmss";

		AVP srvAVP = msg.find(Constants.DIAMETER_AVP_SERVICE_CONTEXT_ID);
		String capabilty = null;
		String capArea = null;
		if (srvAVP != null) {
			String srvCtxID = AVP_UTF8String.queryValue(srvAVP);
			capabilty = DccAvpHelper.getCapability(srvCtxID);
			capArea = DccAvpHelper.getArea(srvCtxID);
		}
		String version = "";
		String code = "";
		if (fromNode == null) {
			version = this.confSrv.getSGWVersion();
			code = this.confSrv.getSGWNeCode();
		} else {
			version = fromNode.getNodeDesc();
			code = fromNode.getNECode();
		}

		AVP avp = null;
		avp = msg.find(Constants.DIAMETER_AVP_srvPlatfrmID, Constants.DIAMETER_VENDOR_CT);
		if (avp == null) {
			if(seq>99999999)
			{
				seq = 0;
			}			
			String srvFlowIDValue = Comutils.formatTime(System.currentTimeMillis(), dateFmt) + String.format("%08d", seq++) + "00" + "-" + confSrv.getAreaCode() + "10" + "-" + code + "014" + "-" + version + "-";
			String flowid = "080000";
			if (capabilty != null) {
				CapabilityCtrlBean capCtrl = this.confSrv.getCapabilityCtrlMap().get(capabilty);
				if (capCtrl != null) {
					flowid = capCtrl.getFlowid();
				}
			}
			srvFlowIDValue += flowid + "-" + capabilty + "@" + capArea + ";";
			avp = new AVP_UTF8String(Constants.DIAMETER_AVP_Service_Flow_Id, Constants.DIAMETER_VENDOR_CT, srvFlowIDValue);
			avp.setMandatory(true);
			msg.add(avp);
		}
	}

	public void setRemovedAVPCodes(Set<Integer> removedAVPCodes) {
		this.removedAVPCodes = removedAVPCodes;
	}
	
	
	public static void setMandatoryAVPs(Message msg) {
		Iterator<AVP> avpItor = msg.iterator();
		// String codeAndInvendor = null;
		AVP avp = null;
		while (avpItor.hasNext()) {
			avp = avpItor.next();
			avp.setMandatory(true);
			if (avp instanceof AVP_Grouped) {
				setMandatoryAVPs((AVP_Grouped) avp);
			}
		}
	}

	public static void setMandatoryAVPs(AVP_Grouped avp) {		
		AVP[] avps = avp.queryAVPs();
		for (int i = 0; i < avps.length; i++) {
			avps[i].setMandatory(true);
			if (avps[i] instanceof AVP_Grouped) {
				setMandatoryAVPs((AVP_Grouped) avps[i]);
			}
		}
		avp.setAVPs(avps);
	}

}
